package com.mhkj.common.shiro;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Component;

import com.mhkj.base.itemInfo.item.entity.Item;
import com.mhkj.base.itemInfo.item.service.ItemService;
import com.mhkj.base.rbac.role.entity.SystemRole;
import com.mhkj.base.rbac.role.service.MyRoleService;
import com.mhkj.base.rbac.user.entity.SystemUser;
import com.mhkj.base.rbac.user.service.SystemUserService;
import com.mhkj.common.constant.Constants;




/**
 * 权限认证
 * @author mics
 * @date 2015-4-22
 * @version 1.0
 */
@Component 
public class AuthorizRealm extends AuthorizingRealm {
	@Resource
	private MyRoleService myRoleService;
	@Resource
	private SystemUserService systemUserService;
	@Resource
	private ItemService itemService;
	
	/**
     * 此方法调用  hasRole,hasPermission的时候才会进行回调.
     *
     * 权限信息.(授权):
     * 1、如果用户正常退出，缓存自动清空；
     * 2、如果用户非正常退出，缓存自动清空；
     * 3、如果我们修改了用户的权限，而用户不退出系统，修改的权限无法立即生效。
     * （需要手动编程进行实现；放在service进行调用）
     * 在权限修改后调用realm中的方法，realm已经由spring管理，所以从spring中获取realm实例，
     * 调用clearCached方法；
     * :Authorization 是授权访问控制，用于对用户进行的操作授权，证明该用户是否允许进行当前操作，如访问某个链接，某个资源文件等。
     * @param principals
     * @return
     */
	@Override       
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();
		@SuppressWarnings("unchecked")
		String currentUsername =  ((Map<String,String>)super.getAvailablePrincipal(principals)).get("username");
		if(currentUsername.equals(Constants.ROOT_NAME)){
			List<String> roleList = new ArrayList<String>();
			roleList.add("root");
			simpleAuthorInfo.addRoles(roleList);
		}else{
			List<Object[]> roles = systemUserService.getUserRole(currentUsername);
			List<String> roleList = new ArrayList<String>();
			for(Object[] obj:roles){
				String roleName = String.valueOf(obj[8]);
				roleList.add(roleName);
			}
			simpleAuthorInfo.addRoles(roleList);
			//simpleAuthorInfo.addStringPermissions(permissionList);
			return simpleAuthorInfo;
		}

      //  info.addStringPermissions(permissions);//将权限放入shiro中.
		return simpleAuthorInfo;
		
	}

	/**
     * 认证信息.(身份验证)
     * Authentication 是用来验证用户身份
     * @param token
     * @return
     * @throws AuthenticationException
     */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
		String loginName = token.getUsername();
		
		Map<String, String> user = new HashMap<String, String>();
		user.put("username", loginName);
		user.put("password", "0000");
		
		AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,"0000", this.getName());
		SystemUser systemUser = new SystemUser();
		if(loginName.equals(Constants.ROOT_NAME)){
			SystemRole systemRole = new SystemRole();
			systemRole.setName("root");
			List<Item> items = itemService.findAll();
			systemRole.setItems(items);
			List<SystemRole> systemRoles = new ArrayList<SystemRole>();
			systemRoles.add(systemRole);
			systemUser.setSystemRoles(systemRoles);
			systemUser.setLoginName(Constants.ROOT_NAME);
		}else{
			systemUser = systemUserService.getByLoginName(loginName);
			if(systemUser == null){
				throw new AuthenticationException("用户名或者密码错误");
			}
			
		}
		setSession(Constants.CURRENT_SYSUSER, systemUser);
		return authenticationInfo;
		
	}

	/**
	 * 将一些数据放到ShiroSession中,以便于其它地方使用
	 * 
	 * @see 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到
	 */

	private void setSession(Object key, Object value) {
		Subject currentUser = SecurityUtils.getSubject();
		if (null != currentUser) {
			Session session = currentUser.getSession();
			if (null != session) {
				session.setAttribute(key, value);
			}
		}
	}

}
